﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Configuration;
using System.ComponentModel;
using System.Data;
//using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Security.AccessControl;
using System.Text;
using System.Threading;
using System.Xml;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Utilities;

using FileMigrateConsole.Properties;
using FileMigrateConsole;

namespace FileMigrateConsole
{
    //   Subfolders are supported; root site and sub site supported
    //   Document libraries are created automatically if no Document Library is specified
    //   the "Created" and "Modified" date of the files and the folders will be changed to the one in the file system
    //   No existing file in the SharePoint site will be overwritten or change
    //   all invalid characters in file name and folder name will be replaced by '_'
    //   don't forget to turn of "versioning" feature and "content approval" workflow of the document library
    //   Three log files will be created in the specified log folder
    //   Please change "Blocked File Types" of the web application before file migrating, and change the "excludeFileTypes" settings in FileMigrateConsole.exe.config
    //   Please change the "logpath" settings in FileMigrateConsole.exe.config
    //   Please change the "FileSizeLimit" settings in FileMigrateConsole.exe.config, and configure SharePoint to allow huge file uploading (if the file size is more than 50MB)
    //   SharePoint 2010 only
    //   Need to be run from the SharePoint server
    class Program
    {
        #region global variables

        //public static string _strFileFolderPath = string.Empty;
        //public static string _strLocalDestinationUrl = string.Empty;
        //public static string _strLocalDestinationSiteUrl = string.Empty;
        //public static string _strLocalDestinationLibName = string.Empty;
        public static string _strFileTarget = string.Empty;

        //  unit: MB
        public static int _iFileSizeLimit = 0;
        public static int _iFileInactiveMonths = 0;
        public static DateTime _dtInactiveDate = DateTime.MinValue;

        public static string[] _strInvalidFileExtensionsArray;

        public static Guid _guidFieldCreated = SPBuiltInFieldId.Created;
        public static Guid _guidFieldModified = SPBuiltInFieldId.Modified;

        public static string _WebGroupName_Owners = string.Empty;
        public static string _WebGroupName_Members = string.Empty;
        public static string _WebGroupName_Visitors = string.Empty;

        public static int _iFileInactiveSkipped = 0;
        public static int _iFileActiveSkipped = 0;
        public static int _iFileCopied = 0;
        public static int _iFilePermissionCopied = 0;
        public static int _iFolderCopied = 0;
        public static int _iFolderPermissionCopied = 0;

        public static bool _boolCopyPermissions = Settings.Default.CopyPermissions;
        public static bool _boolCopyFiles = Settings.Default.CopyFiles;
        public static bool _boolFileNameUniqueID = Settings.Default.FileNameUniqueID;
        public static bool _boolFileLockFlag = false;

        public static Collection<string> _blockedFileTypes;

        public enum SiteFolderType
        {
            Site,
            List,
            Folder,
            Invalid
        }

        //public static SiteFolderType _siteFolderType;
        //public static SPFolder _siteSPFolder;

        #endregion

        #region common functions
        private static void writeDebugInfo(string strMsg)
        {
            CommonTool.writeDebugInfo(@"FileMigrate_debug", strMsg);
        }

        private static void writeCheckInfo(string strMsg)
        {
            CommonTool.sysWriteAppEntry(@"FileMigrate_check", strMsg, true);
        }

        private static void writeCompareInfo(string strMsg)
        {
            CommonTool.sysWriteAppEntry(@"FileMigrate_compare", strMsg, true);
        }

        private static void writeLog(string strMsg)
        {
            CommonTool.sysWriteAppEntry(@"FileMigrate_log", strMsg, true);
            //Console.ReadLine();
        }

        private static void writeSkippedFileLog(string strMsg)
        {
            CommonTool.sysWriteAppEntry(@"FileMigrate_skipped", strMsg, false);
        }

        public static bool getGroupNames(string strLocalDestinationUrl)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite objSPSite = new SPSite(strLocalDestinationUrl))
                {
                    using (SPWeb objSPWeb = objSPSite.OpenWeb())
                    {
                        foreach (SPGroup objSPGroup in objSPWeb.Groups)
                        {
                            if (objSPGroup.Name.Contains("Owners"))
                            {
                                _WebGroupName_Owners = objSPGroup.Name;
                            }
                            else if (objSPGroup.Name.Contains("Members"))
                            {
                                _WebGroupName_Members = objSPGroup.Name;
                            }
                            else if (objSPGroup.Name.Contains("Visitors"))
                            {
                                _WebGroupName_Visitors = objSPGroup.Name;
                            }
                        }
                    }
                }
            });

            return true;
        }

        #endregion

        public static void checkFiles(string strFolderPath)
        {
            _iFolderCopied++;

            string strFilePathTooLongMessage = string.Empty;
            string strTmp = string.Empty;
            int iFolderPathLength = strFolderPath.Length;
            if (iFolderPathLength > 250)
            {
                strTmp = string.Format(@"Folder path too long '{0}'", strFolderPath);
                writeCheckInfo(strTmp);
                return;
            }

            DirectoryInfo dirinfo = new DirectoryInfo(strFolderPath);
            string strSPFolderName = convertFolderName(dirinfo.Name);
            string strParentFolder = string.Empty;
            if (dirinfo.Name.Equals(strSPFolderName, StringComparison.InvariantCultureIgnoreCase) == false)
            {
                if (dirinfo.Parent != null)
                {
                    strParentFolder = dirinfo.Parent.FullName;
                }
                else
                {
                    strParentFolder = string.Empty;
                }
                //strTmp = string.Format("Folder path will be converted. Original: '{0}', Converted: '{1}'\nParent folder='{2}'", dirinfo.Name, strSPFolderName, strParentFolder);
                //writeCheckInfo(strTmp);
            }

            FileInfo[] oFiles;
            try
            {
                oFiles = dirinfo.GetFiles();
                if (oFiles.Length > 5000)
                {
                    strTmp = string.Format(@"There are '{0}' files in folder path '{1}', only 5000 files will be uploaded!", oFiles.Length, strFolderPath);
                    writeCheckInfo(strTmp);
                }
            }
            catch (Exception ex)
            {
                strTmp = string.Format(@"Cannot get files from folder path '{0}'", strFolderPath);
                writeCheckInfo(strTmp);
                writeDebugInfo(string.Format(@"checkFiles(), ex.Message={0}", ex.Message));
                writeDebugInfo(string.Format(@"checkFiles(), ex.StackTrace={0}", ex.StackTrace));
                return;
            }
            string strFileName = string.Empty;
            int iFileNameLength = int.MinValue;
            foreach (FileInfo oCurrentFile in oFiles)
            {
                _iFileCopied++;

                strFileName = oCurrentFile.Name;
                if (string.IsNullOrEmpty(oCurrentFile.Extension))
                {
                    strTmp = string.Format(@"File type is empty '{0}\{1}'", strFolderPath, strFileName);
                    writeCheckInfo(strTmp);
                    continue;
                }

                if (InvalidFileExtention(oCurrentFile.Extension) || InvalidFileName(strFileName))
                {
                    //strTmp = string.Format(@"File type or file name is invalid '{0}\{1}'", strFolderPath, strFileName);
                    //writeCheckInfo(strTmp);
                    continue;
                }

                if (iFolderPathLength + strFileName.Length > 259)
                {
                    //strFilePathTooLongMessage = string.Format(@"File path too long '{0}\{1}'", strFolderPath, strFileName);
                    continue;
                }
                iFileNameLength = strFileName.Length;
                if (iFileNameLength > 128)
                {
                    strTmp = string.Format(@"File name too long '{0}\{1}'", strFolderPath, strFileName);
                    writeCheckInfo(strTmp);
                    continue;
                }
                try
                {
                    if (oCurrentFile.Length > _iFileSizeLimit)
                    {
                        strTmp = string.Format(@"File too big({2}), '{0}\{1}'", strFolderPath, strFileName, oCurrentFile.Length);
                        writeCheckInfo(strTmp);
                    }
                }
                catch
                {
                    //strFilePathTooLongMessage = string.Format(@"File path too long '{0}\{1}'", strFolderPath, strFileName);
                    continue;
                }
            }

            if (string.IsNullOrEmpty(strFilePathTooLongMessage) == false)
            {
                writeCheckInfo(strFilePathTooLongMessage);
            }

            DirectoryInfo[] oSubFolders = dirinfo.GetDirectories();
            if (oSubFolders.Length > 5000)
            {
                strTmp = string.Format(@"There are '{0}' sub folders in folder path '{1}', only 5000 files will be uploaded!", oSubFolders.Length, strFolderPath);
                writeCheckInfo(strTmp);
            }
            foreach (DirectoryInfo objDirectoryInfo in oSubFolders)
            {
                checkFiles(string.Format(@"{0}\{1}", strFolderPath, objDirectoryInfo.Name));
            }

            return;
        }

        public static SPFile uploadFile(FileInfo oCurrentFile, SPFolder objSPFolder, string strFileName)
        {
            try
            {
                //writeDebugInfo(string.Format(@"uploadFile() begin, FileName={0}, SPFolder.Url={1}", strFileName, objSPFolder.Url));

                FileStream fStream = oCurrentFile.OpenRead();
                byte[] content = new byte[fStream.Length];
                int c = fStream.Read(content, 0, (int)fStream.Length);
                fStream.Close();

                SPFileCollection objSPFileCollection = objSPFolder.Files;

                objSPFileCollection.Web.AllowUnsafeUpdates = true;
                string strFileId = convertFileName(oCurrentFile.Name);
                if (string.IsNullOrEmpty(strFileName) == false)
                {
                    strFileId = strFileName;
                }
                SPFile oSPFile = objSPFileCollection.Add(strFileId, content);

                oSPFile.Item[_guidFieldCreated] = oCurrentFile.CreationTime;
                oSPFile.Item[_guidFieldModified] = oCurrentFile.LastWriteTime;
                oSPFile.Item[SPBuiltInFieldId.Title] = oCurrentFile.Name;
                oSPFile.Item.UpdateOverwriteVersion();

                if (oSPFile.CheckOutType != SPFile.SPCheckOutType.None)
                    oSPFile.CheckIn(string.Empty, SPCheckinType.MajorCheckIn);

                if (_boolCopyPermissions && oSPFile != null)
                {
                    copyFilePermissions(oCurrentFile, oSPFile);
                }

                return oSPFile;
            }
            catch (Exception ex)
            {
                writeDebugInfo(string.Format(@"uploadFile(), FileName={0}, SPFolder.Url={1}", strFileName, objSPFolder.Url));
                writeDebugInfo(string.Format(@"uploadFile(), ex.Message={0}", ex.Message));
                writeDebugInfo(string.Format(@"uploadFile(), ex.StackTrace={0}", ex.StackTrace));

                if (ex.Message.Contains(@"cannot be accessed"))
                {
                    _boolFileLockFlag = true;
                    writeDebugInfo(string.Format(@"uploadFile(), Cannot access, File.FullName={0}", oCurrentFile.FullName));
                }
            }

            return null;
        }

        public static bool copyFilePermissions(FileInfo oCurrentFile, SPFile oSPFile)
        {
            try
            {
                FileSecurity objFileSecurity = oCurrentFile.GetAccessControl();
                AuthorizationRuleCollection objRules = objFileSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
                changeSPListItemRights(oSPFile.Item, objRules);
            }
            catch (Exception ex)
            {
                writeDebugInfo(string.Format(@"copyFilePermissions(), oCurrentFile.Name={0}, oSPFile.Url={1}", oCurrentFile.Name, oSPFile.Url));
                writeDebugInfo(string.Format(@"copyFilePermissions(), ex.Message={0}", ex.Message));
                writeDebugInfo(string.Format(@"copyFilePermissions(), ex.StackTrace={0}", ex.StackTrace));

                return false;
            }

            return true;
        }

        public static SPFolder createFolder(SPFolder objSPFolderParent, DirectoryInfo objSubDirectoryInfo)
        {
            SiteFolderType objSiteFolderType = getSiteFolderType(objSPFolderParent);
            SPFolder objSPFolder = null;
            string strSubSiteFolderUrl = string.Empty;
            string strSubFolderName = string.Empty;
            SPWeb objSPWeb = null;
            objSPWeb = objSPFolderParent.ParentWeb;

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                objSPWeb.AllowUnsafeUpdates = true;
                strSubSiteFolderUrl = string.Empty;

                if (objSiteFolderType == SiteFolderType.Site)
                {
                    strSubFolderName = convertListName(objSubDirectoryInfo.Name);
                    SPList objSPList = objSPWeb.Lists.TryGetList(strSubFolderName);
                    if (objSPList == null)
                    {
                        Guid objListGuid = objSPWeb.Lists.Add(strSubFolderName, objSubDirectoryInfo.Name, SPListTemplateType.DocumentLibrary);
                        objSPList = objSPWeb.Lists.GetList(objListGuid, true);
                        objSPList.OnQuickLaunch = true;
                        objSPList.Update();
                        writeDebugInfo(string.Format(@"Library '{0}' is created.", objSPList.RootFolder.Url));
                    }
                    else
                    {
                        writeDebugInfo(string.Format(@"Library '{0}' exist.", objSPList.RootFolder.Url));
                    }

                    objSPFolder = objSPList.RootFolder;
                }
                else
                {
                    strSubFolderName = convertFolderName(objSubDirectoryInfo.Name);
                    strSubSiteFolderUrl = string.Format("{0}/{1}", objSPFolderParent.Url, strSubFolderName);
                    objSPFolder = objSPWeb.GetFolder(strSubSiteFolderUrl);
                    if (objSPFolder.Exists == false && _boolCopyFiles == true)
                    {
                        objSPFolder = objSPFolderParent.SubFolders.Add(strSubSiteFolderUrl);
                        objSPFolder.Item[_guidFieldCreated] = objSubDirectoryInfo.CreationTime;
                        objSPFolder.Item[_guidFieldModified] = objSubDirectoryInfo.LastWriteTime;
                        objSPFolder.Item[SPBuiltInFieldId.Title] = objSubDirectoryInfo.Name;
                        objSPFolder.Item.UpdateOverwriteVersion();
                        writeDebugInfo(string.Format(@"Sub folder '{0}' created.", objSPFolder.Url));
                    }
                    else
                    {
                        writeDebugInfo(string.Format(@"Sub folder '{0}' exist.", objSPFolder.Url));
                    }
                }
                writeDebugInfo(string.Format(@"uploadFolder(), strSubSiteFolderUrl='{0}'.", strSubSiteFolderUrl));
            });

            return objSPFolder;
        }
         
        public static int uploadFolder(DirectoryInfo objParentDirectoryInfo, SPFolder objSPFolderParent)
        {
            int iSubFolderCount = 0;
            string strFolderName = objParentDirectoryInfo.Name;
            string strTmp = string.Empty;

            SiteFolderType objSiteFolderType = getSiteFolderType(objSPFolderParent);
            SPFolder objSPFolder = null;
            string strSubSiteFolderUrl = string.Empty;
            SPWeb objSPWeb = null;
            objSPWeb = objSPFolderParent.ParentWeb;

            DirectoryInfo[] oSubFolders = objParentDirectoryInfo.GetDirectories();
            if (oSubFolders.Length > 5000)
            {
                strTmp = string.Format(@"There are '{0}' sub folders in folder path '{1}', only 5000 files will be uploaded!", oSubFolders.Length, objParentDirectoryInfo.FullName);
                writeCheckInfo(strTmp);
            }
            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    foreach (DirectoryInfo objSubDirectoryInfo in oSubFolders)
                    {
                        objSPWeb.AllowUnsafeUpdates = true;
                        strSubSiteFolderUrl = string.Empty;

                        objSPFolder = createFolder(objSPFolderParent, objSubDirectoryInfo);
                        strSubSiteFolderUrl = objSPFolder.ServerRelativeUrl;
                        writeDebugInfo(string.Format(@"uploadFolder(), strSubSiteFolderUrl='{0}'.", strSubSiteFolderUrl));

                        if (objSPFolder != null)
                        {
                            uploadFolder(objSubDirectoryInfo, objSPFolder);

                            iSubFolderCount++;
                        }
                        else
                        {
                            if (_boolCopyPermissions == true)
                            {
                                copyFolderPermissions(objSubDirectoryInfo, objSPFolder);
                            }

                            writeDebugInfo(string.Format(@"Cannot create folder '{0}'.", strSubSiteFolderUrl));
                        }
                    }

                    UploadFiles(objParentDirectoryInfo.FullName, objSPFolderParent);
                });
            }
            catch (Exception ex)
            {
                writeLog(string.Format(@"uploadFolder(), objParentDirectoryInfo.FullName={0}, objSPFolderParent.Url={1}, iSubFolderCount={2}", objParentDirectoryInfo.FullName, objSPFolderParent.Url, iSubFolderCount));
                writeLog(string.Format(@"uploadFolder(), ex.Message={0}", ex.Message));
                writeLog(string.Format(@"uploadFolder(), ex.StackTrace={0}", ex.StackTrace));

                return iSubFolderCount;
            }
            finally
            {
                objSPFolderParent.ParentWeb.AllowUnsafeUpdates = false;
            }

            return iSubFolderCount;
        }

        public static bool copyFolderPermissions(DirectoryInfo dirinfo, SPFolder mySubFolder)
        {
            try
            {
                DirectorySecurity objDirectorySecurity = dirinfo.GetAccessControl();
                AuthorizationRuleCollection objRules = objDirectorySecurity.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));

                if (string.IsNullOrEmpty(mySubFolder.ParentFolder.Name))
                {   //for document library
                    changeSPListRights(mySubFolder.ParentWeb.Lists[mySubFolder.ParentListId], objRules);
                }
                else
                {
                    changeSPListItemRights(mySubFolder.Item, objRules);
                }
            }
            catch (Exception ex)
            {
                writeLog(string.Format(@"copyFolderPermissions(), dirinfo.Name={0}, mySubFolder.Url={1}", dirinfo.Name, mySubFolder.Url));
                writeLog(string.Format(@"copyFolderPermissions(), ex.Message={0}", ex.Message));
                writeLog(string.Format(@"copyFolderPermissions(), ex.StackTrace={0}", ex.StackTrace));
                return false;
            }

            return true;
        }

        public static void getBlockedFileTypes(string strSiteUrl)
        {
            writeDebugInfo(@"getBlockedFileTypes() begin...");

            try
            {
                //SPSecurity.RunWithElevatedPrivileges(delegate()
                //{
                SPWebApplication myWebApp = SPWebApplication.Lookup(new Uri(strSiteUrl));
                _blockedFileTypes = myWebApp.BlockedFileExtensions;
                //using (SPSite objSPSite = new SPSite(strSiteUrl))
                //{
                //    string strTmp = string.Format(@"getBlockedFileTypes() - strSiteUrl='{0}', objSPSite.ServerRelativeUrl='{1}'", strSiteUrl, objSPSite.ServerRelativeUrl);
                //    writeDebugInfo(strTmp);
                //    SPWebApplication myWebApp = new SPSite(strSiteUrl).WebApplication;
                //    _blockedFileTypes = myWebApp.BlockedFileExtensions;
                //}
                //});
            }
            catch (Exception ex)
            {
                writeDebugInfo(string.Format(@"getBlockedFileTypes(), ex.Message={0}", ex.Message));
                writeDebugInfo(string.Format(@"getBlockedFileTypes(), ex.StackTrace={0}", ex.StackTrace));
                string strTmp = string.Format(@"getBlockedFileTypes() - No rights to get 'Blocked File Types' from SharePoint site, SiteUrl='{0}'", strSiteUrl);
                writeDebugInfo(strTmp);
                Console.WriteLine("Do you want to continue? ([Y]es, [N]o, yes for [A]ll)");
                string strRead = Console.ReadLine();
                if (strRead.Equals(@"Y", StringComparison.InvariantCultureIgnoreCase))
                {
                    return;
                }
                else
                {
                    Console.WriteLine("Exited.");
                    System.Environment.Exit(0);
                }
            }
        }

        public static SPFolder getSPFolderByUrl(string strSiteFolderUrl)
        {
            string strTmp = string.Empty;
            SPFolder objSPFolder = null;
            try
            {
                using (SPSite objSPSite = new SPSite(strSiteFolderUrl))
                {
                    using (SPWeb objSPWeb = objSPSite.OpenWeb())
                    {
                        objSPFolder = objSPWeb.GetFolder(strSiteFolderUrl);
                        if (objSPFolder.Exists == false)
                        {
                            objSPFolder = null;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                strTmp = string.Format(@"getSPFolderByUrl(), Exception, strSiteFolderUrl='{0}'", strSiteFolderUrl);
                writeLog(strTmp);
                writeLog(string.Format(@"getSPFolderByUrl(), ex.Message={0}", ex.Message));
                writeLog(string.Format(@"getSPFolderByUrl(), ex.StackTrace={0}", ex.StackTrace));
            }

            return objSPFolder;
        }

        public static SiteFolderType getSiteFolderType(SPFolder objSPFolder)
        {
            string strTmp = string.Empty;
            SiteFolderType objSiteFolderType;

            try
            {
                if (objSPFolder.Exists == false)
                {
                    return SiteFolderType.Invalid;
                }
                if (string.IsNullOrEmpty(objSPFolder.ParentFolder.Name))
                {
                    if (string.IsNullOrEmpty(objSPFolder.Name))
                    {
                        objSiteFolderType = SiteFolderType.Site;
                    }
                    else
                    {
                        objSiteFolderType = SiteFolderType.List;
                    }
                }
                else
                {
                    objSiteFolderType = SiteFolderType.Folder;
                }
            }
            catch (Exception ex)
            {
                strTmp = string.Format(@"getSiteFolderType(), Exception, objSPFolder.Url='{0}'", objSPFolder.Url);
                writeCompareInfo(strTmp);
                writeDebugInfo(strTmp);
                writeDebugInfo(string.Format(@"getSiteFolderType(), ex.Message={0}", ex.Message));
                writeDebugInfo(string.Format(@"getSiteFolderType(), ex.StackTrace={0}", ex.StackTrace));
                objSiteFolderType = SiteFolderType.Invalid;
            }

            //writeDebugInfo(string.Format(@"getSiteFolderType(), SiteFolderType={0}", _siteFolderType));

            return objSiteFolderType;
        }

        public static void compareFiles(DirectoryInfo dirinfoParent, SPFolder objSPFolderParent)
        {
            string strTmp = string.Empty;
            //strTmp = string.Format(@"compareFiles() - strFolderPath='{0}', strSiteFolderUrl='{1}', strCurrentSubFolderName='{2}', ", strFolderPath, strSiteFolderUrl, strCurrentSubFolderName);
            //writeDebugInfo(strTmp);

            writeDebugInfo(@".");

            string strFileName = string.Empty;
            string strSubFolderName = string.Empty;
            string strSiteFileName = string.Empty;
            string strSiteSubFolderName = string.Empty;
            string strSiteSubFileUrl = string.Empty;
            string strSiteSubFolderUrl = string.Empty;
            string strSiteFolderUrl = string.Empty;

            SPFile objSPFile = null;
            SPWeb objSPWeb = objSPFolderParent.ParentWeb;
            SPFolder objSubSPFolder = null;
            string strRead = string.Empty;

            _iFolderCopied++;

            string strFilePathTooLongMessage = string.Empty;
            int iFolderPathLength = int.MinValue;

            SiteFolderType objSiteFolderType = getSiteFolderType(objSPFolderParent);

            try
            {
                strSiteFolderUrl = objSPFolderParent.ServerRelativeUrl;
                if (strSiteFolderUrl.EndsWith(@"/"))
                    strSiteFolderUrl = strSiteFolderUrl.Substring(0, strSiteFolderUrl.Length - 1);

                DirectoryInfo[] oSubFolders = dirinfoParent.GetDirectories();
                foreach (DirectoryInfo objSubDirectoryInfo in oSubFolders)
                {
                    iFolderPathLength = objSubDirectoryInfo.FullName.Length;
                    if (iFolderPathLength > 250)
                    {
                        strTmp = string.Format(@"Folder path too long '{0}'", objSubDirectoryInfo.FullName);
                        writeCompareInfo(strTmp);
                        continue;
                    }

                    strSubFolderName = objSubDirectoryInfo.Name;
                    if (objSiteFolderType == SiteFolderType.Site)
                    {
                        strSiteSubFolderName = convertListName(strSubFolderName);
                    }
                    else
                    {
                        strSiteSubFolderName = convertFolderName(strSubFolderName);
                    }

                    strSiteSubFolderUrl = string.Format(@"{0}/{1}", strSiteFolderUrl, strSiteSubFolderName);
                    objSubSPFolder = objSPWeb.GetFolder(strSiteSubFolderUrl);
                    if (objSubSPFolder.Exists == false)
                    {
                        strTmp = string.Format(@"dest folder doesn't exist! Source='{0}', dest='{1}', folder name='{2}'", dirinfoParent.FullName, strSiteFolderUrl, objSubDirectoryInfo.Name);
                        writeCompareInfo(strTmp);
                        while (strRead.Equals(@"Y", StringComparison.InvariantCultureIgnoreCase) == false
                            && strRead.Equals(@"N", StringComparison.InvariantCultureIgnoreCase) == false)
                        {
                            Console.WriteLine("Do you want to create this folder? ([Y]es, [N]o)");
                            strRead = Console.ReadLine();
                            //strRead = @"Y";
                        }
                        if (strRead.Equals(@"Y", StringComparison.InvariantCultureIgnoreCase))
                        {
                            objSubSPFolder = createFolder(objSPFolderParent, objSubDirectoryInfo);
                        }
                        else
                        {
                            continue;
                        }
                    }

                    //compareFiles(string.Format(@"{0}\{1}", strFolderPath, strSubFolderName), string.Format(@"{0}/{1}", strSiteFolderUrl, strSiteSubFolderName));
                    compareFiles(objSubDirectoryInfo, objSubSPFolder);
                }

                FileInfo[] oFiles;
                if (objSiteFolderType == SiteFolderType.Site)
                {
                    return;
                }

                try
                {
                    oFiles = dirinfoParent.GetFiles();
                }
                catch (Exception ex)
                {
                    strTmp = string.Format(@"Cannot get files from folder path '{0}'", dirinfoParent.FullName);
                    writeCompareInfo(strTmp);
                    writeDebugInfo(strTmp);
                    writeDebugInfo(string.Format(@"compareFiles(), ex.Message={0}", ex.Message));
                    writeDebugInfo(string.Format(@"compareFiles(), ex.StackTrace={0}", ex.StackTrace));
                    return;
                }

                foreach (FileInfo oCurrentFile in oFiles)
                {
                    _iFileCopied++;

                    strFileName = oCurrentFile.Name;
                    if (InvalidFileName(strFileName))
                    {
                        continue;
                    }
                    if (InvalidFileExtention(oCurrentFile.Extension))
                    {
                        continue;
                    }

                    if (_boolFileLockFlag)
                    {
                        bool boolIsLocked = IsFileLocked(oCurrentFile);
                        if (boolIsLocked)
                        {
                            strTmp = string.Format(@"file locked! Source='{0}\{1}'", dirinfoParent.FullName, strFileName);
                            writeCompareInfo(strTmp);
                            continue;
                        }
                    }

                    strSiteFileName = convertFileName(strFileName);
                    strSiteSubFileUrl = string.Format(@"{0}/{1}", strSiteFolderUrl, strSiteFileName);
                    objSPFile = objSPWeb.GetFile(strSiteSubFileUrl);
                    if (objSPFile.Exists == false)
                    {
                        strTmp = string.Format(@"dest file doesn't exist! Source='{0}\{1}', dest='{2}'", dirinfoParent.FullName, strFileName, strSiteSubFileUrl);
                        writeCompareInfo(strTmp);
                        strTmp = string.Format(@"oCurrentFile={0}.LastWriteTime", oCurrentFile.LastWriteTime);
                        writeCompareInfo(strTmp);
                        if (strRead.Equals(@"I", StringComparison.InvariantCultureIgnoreCase))
                        {
                            continue;
                        }
                        if (strRead.Equals(@"A", StringComparison.InvariantCultureIgnoreCase))
                        {
                            objSPFile = uploadFile(oCurrentFile, objSPFolderParent, strSiteFileName);
                            continue;
                        }
                        while (strRead.Equals(@"Y", StringComparison.InvariantCultureIgnoreCase) == false
                            && strRead.Equals(@"N", StringComparison.InvariantCultureIgnoreCase) == false
                            && strRead.Equals(@"A", StringComparison.InvariantCultureIgnoreCase) == false
                            && strRead.Equals(@"I", StringComparison.InvariantCultureIgnoreCase) == false)
                        {
                            Console.WriteLine("Do you want to upload this file (in current folder)? ([Y]es, [N]o, [A]ll, [I]gnore all)");
                            strRead = Console.ReadLine();
                            //strRead = @"A";
                        }
                        if (strRead.Equals(@"Y", StringComparison.InvariantCultureIgnoreCase)
                            || strRead.Equals(@"A", StringComparison.InvariantCultureIgnoreCase))
                        {
                            objSPFile = uploadFile(oCurrentFile, objSPFolderParent, strSiteFileName);
                            writeCompareInfo(@"uploaded");
                        }
                        if (strRead.Equals(@"Y", StringComparison.InvariantCultureIgnoreCase)
                            || strRead.Equals(@"N", StringComparison.InvariantCultureIgnoreCase))
                        {
                            strRead = string.Empty;
                        }
                    }
                }   //   end of "foreach (FileInfo oCurrentFile in oFiles)"

                if (_boolCopyPermissions == true && objSiteFolderType != SiteFolderType.Site)
                {
                    copyFolderPermissions(dirinfoParent, objSPFolderParent);
                }

            }
            catch (Exception ex)
            {
                strTmp = string.Format(@"Ex! source file='{0}', dest file='{1}'", strFileName, strSiteFileName);
                writeCompareInfo(strTmp);
                writeDebugInfo(strTmp);
                strTmp = string.Format(@"Ex! source folder='{0}', dest folder='{1}'", strSubFolderName, strSiteSubFolderName);
                writeCompareInfo(strTmp);
                writeDebugInfo(strTmp);
                writeDebugInfo(string.Format(@"compareFiles(), ex.Message={0}", ex.Message));
                writeDebugInfo(string.Format(@"compareFiles(), ex.StackTrace={0}", ex.StackTrace));
                throw;
            }

            return;
        }

        static void Main(string[] args)
        {
            if (args.Length != 2 && args.Length != 3 && args.Length != 5 && args.Length != 6)
            {
                writeLog(@"invalid parameters.");
                writeLog(@"parameters: source folder path, site collection url, sub site url, document name(appear in url), subfolder name(optional)");
                writeLog(@"sample 1: FileMigrateConsole.exe active '\\remoteServer\d$\folder1\subfolder1' 'http://SharePointServer:port/Lib1'");
                writeLog(@"sample 2: FileMigrateConsole.exe inactive '\\remoteServer\d$\folder1\subfolder1' 'http://SharePointServer:port/Lib1/Subfolder1'");
                writeLog(@"sample 3: FileMigrateConsole.exe all '\\remoteServer\d$\folder1\subfolder1' 'http://SharePointServer:port/sites/site1/Lib1/Subfolder1'");
                writeLog(@"sample 4: FileMigrateConsole.exe check '\\remoteServer\d$\folder1\subfolder1'");
                writeLog(@"sample 5: FileMigrateConsole.exe compare '\\remoteServer\d$\folder1\subfolder1' 'http://SharePointServer:port/sites/site1'");
                writeLog(@"sample 6: FileMigrateConsole.exe compare '\\remoteServer\d$\folder1\subfolder1' 'http://SharePointServer:port/sites/site1/Lib1/Subfolder1'");
                return;
            }

            _strInvalidFileExtensionsArray = Settings.Default.excludeFileTypes.Split(new char[] { ';' });
            _iFileSizeLimit = int.Parse(Settings.Default.FileSizeLimit) * 1024 * 1024;

            _iFileInactiveMonths = Settings.Default.InactiveMonths;
            _dtInactiveDate = DateTime.Today.AddMonths(0 - _iFileInactiveMonths);

            _strFileTarget = args[0];

            string strFileFolderPath = args[1];
            writeLog("File Folder Path=" + strFileFolderPath);
            if (Directory.Exists(strFileFolderPath) == false)
            {
                writeLog(string.Format(@"Source Folder ({0}) doesn't exist!", strFileFolderPath));
                return;
            }
            DirectoryInfo dirinfo = new DirectoryInfo(strFileFolderPath);

            if (args.Length == 2 && _strFileTarget.Equals("check", StringComparison.InvariantCultureIgnoreCase))
            {
                getBlockedFileTypes("http://localhost");
                checkFiles(strFileFolderPath);
                writeLog(string.Format(@"Folders and files path's length check completed. Folder count={0}, file count={1}", _iFolderCopied, _iFileCopied));
                return;
            }

            string strLocalDestinationUrl = args[2];
            if (strLocalDestinationUrl.EndsWith(@"/"))
                strLocalDestinationUrl = strLocalDestinationUrl.Substring(0, strLocalDestinationUrl.Length - 1);
            writeLog("Local Destination Url=" + strLocalDestinationUrl);

            SPFolder objRootSPFolder = null;
            objRootSPFolder = getSPFolderByUrl(strLocalDestinationUrl);
            if (null == objRootSPFolder)
            {
                writeLog(string.Format(@"Site folder url '{0}' is invalid", strLocalDestinationUrl));
                return;
            }

            getBlockedFileTypes(strLocalDestinationUrl);
            //foreach (string item in _blockedFileTypes)
            //{
            //    Console.WriteLine(item);
            //}
            //return;

            if (args.Length == 3 && _strFileTarget.Equals("compare", StringComparison.InvariantCultureIgnoreCase))
            {
                compareFiles(dirinfo, objRootSPFolder);
                writeLog(string.Format(@"Folders and files's comparison completed. Folder count={0}, file count={1}", _iFolderCopied, _iFileCopied));
                return;
            }

            writeLog(string.Format(@"Settings.Default.CopyPermissions=", _boolCopyPermissions));
            writeLog(string.Format(@"Settings.Default.CopyFiles=", _boolCopyFiles));
            writeLog(string.Format(@"Settings.Default.FileNameUniqueID=", _boolFileNameUniqueID));

            if (Settings.Default.CopyPermissions == false && Settings.Default.CopyFiles == false)
            {
                writeLog(string.Format(@"CopyPermissions=false and CopyFiles=false, so nothing need to do. Exit."));
                return;
            }

            getGroupNames(strLocalDestinationUrl);

            uploadFolder(dirinfo, objRootSPFolder);

            writeLog(string.Format(@"FileInactiveSkipped = {0}, FileActiveSkipped = {1}", _iFileInactiveSkipped, _iFileActiveSkipped));
            writeLog(string.Format(@"File Copied = {0}, File Permission Copied = {1}", _iFileCopied, _iFilePermissionCopied));
            writeLog(string.Format(@"Folder Copied = {0}, Folder Permission Copied = {1}", _iFolderCopied, _iFolderPermissionCopied));
            writeLog(string.Format(@"Complete", _iFileInactiveSkipped));
        }

        public static bool resetReadOnlyFields(SPList objParaSPList, bool boolReadOnly)
        {
            SPList oSPList = null;

            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite objSPSite = new SPSite(objParaSPList.ParentWeb.Site.ID))
                {
                    using (SPWeb objSPWeb = objSPSite.OpenWeb(objParaSPList.ParentWeb.ID))
                    {
                        objSPWeb.AllowUnsafeUpdates = true;
                        string strWebUrl = objSPWeb.ServerRelativeUrl;
                        if (strWebUrl.EndsWith(@"/") == false)
                        {
                            strWebUrl += @"/";
                        }
                        try
                        {
                            oSPList = objSPWeb.Lists.TryGetList(oSPList.Title);
                            if (oSPList == null)
                            {
                                writeLog(string.Format(@"resetReadOnlyFields(), library name not valid, strWebUrl={0}, strLibName={1}", strWebUrl, objParaSPList.Title));
                            }
                            else
                            {
                                oSPList.Fields[_guidFieldCreated].ReadOnlyField = boolReadOnly;
                                oSPList.Fields[_guidFieldCreated].Update();
                                oSPList.Fields[_guidFieldModified].ReadOnlyField = boolReadOnly;
                                oSPList.Fields[_guidFieldModified].Update();
                                oSPList.Update();
                            }
                        }
                        catch (Exception ex)
                        {
                            writeDebugInfo(string.Format(@"resetReadOnlyFields(), ex, strWebUrl={0}, strLibName={1}", strWebUrl, objParaSPList.Title));
                            writeDebugInfo(string.Format(@"resetReadOnlyFields(), ex.Message={0}", ex.Message));
                            writeDebugInfo(string.Format(@"resetReadOnlyFields(), ex.StackTrace={0}", ex.StackTrace));

                            throw;
                        }
                        finally
                        {
                            if (objSPWeb != null)
                            {
                                objSPWeb.AllowUnsafeUpdates = false;
                            }
                        }
                    }
                }
            });

            return true;
        }

        public static SPRoleDefinition getSPRoleDefinition(SPWeb objSPWeb, string strFileSystemRights)
        {
            SPRoleDefinition RoleDefinition = null;
            if (strFileSystemRights.Contains("FullControl"))
            {
                RoleDefinition = objSPWeb.RoleDefinitions.GetByType(SPRoleType.Administrator);
            }
            else if (strFileSystemRights.ToString().Contains("Modify"))
            {
                RoleDefinition = objSPWeb.RoleDefinitions.GetByType(SPRoleType.Contributor);
            }
            else if (strFileSystemRights.ToString().Contains("Read"))
            {
                RoleDefinition = objSPWeb.RoleDefinitions.GetByType(SPRoleType.Reader);
            }
            else
            {
                RoleDefinition = null;
            }
            return RoleDefinition;
        }

        public static bool changeSPListRights(SPList objSPList, AuthorizationRuleCollection objRules)
        {
            if (Settings.Default.CopyPermissions == false)
                return false;

            if (objSPList.HasUniqueRoleAssignments == true)
                return false;

            bool boolBreakRoleInheritance = false;
            bool boolPermissionAdded = false;
            SPWeb objSPWeb = objSPList.ParentWeb;
            string strDomainPrefix = System.Environment.UserDomainName + @"\";

            try
            {
                objSPWeb.AllowUnsafeUpdates = true;

                foreach (System.Security.AccessControl.FileSystemAccessRule objAccessRule in objRules)
                {
                    if (objAccessRule.IsInherited == false && objAccessRule.AccessControlType == AccessControlType.Allow && objAccessRule.IdentityReference.Value.StartsWith(strDomainPrefix, StringComparison.InvariantCultureIgnoreCase))
                    {
                        objSPList.BreakRoleInheritance(false);
                        SPRoleDefinition RoleDefinition = objSPWeb.RoleDefinitions.GetByType(SPRoleType.Administrator);
                        SPRoleAssignment RoleAssignment = null;

                        boolPermissionAdded = false;
                        if (Settings.Default.SitesAdminFullControl == true)
                        {
                            RoleAssignment = new SPRoleAssignment((SPPrincipal)objSPWeb.Site.Owner);
                            RoleAssignment.RoleDefinitionBindings.Add(RoleDefinition);
                            objSPList.RoleAssignments.Add(RoleAssignment);
                            boolPermissionAdded = true;
                        }

                        if (Settings.Default.SitesAdminFullControl == true)
                        {
                            RoleAssignment = new SPRoleAssignment((SPPrincipal)objSPWeb.Groups[_WebGroupName_Owners]);
                            RoleAssignment.RoleDefinitionBindings.Add(RoleDefinition);
                            objSPList.RoleAssignments.Add(RoleAssignment);
                            boolPermissionAdded = true;
                        }

                        if (boolPermissionAdded == true)
                        {
                            objSPList.Update();
                        }
                        boolBreakRoleInheritance = true;
                        break;
                    }
                }
                if (boolBreakRoleInheritance == false)
                {
                    return false;
                }

                writeDebugInfo(string.Format(@"changeSPListRights(), objSPList.RootFolder.Url={0}", objSPList.RootFolder.Url));
                foreach (System.Security.AccessControl.FileSystemAccessRule objAccessRule in objRules)
                {
                    if (objAccessRule.AccessControlType == AccessControlType.Allow && objAccessRule.IdentityReference.Value.StartsWith(strDomainPrefix, StringComparison.InvariantCultureIgnoreCase))
                    {
                        string strUserLoginName = objAccessRule.IdentityReference.Value;
                        string strUserDisplayName = strUserLoginName;

                        string strRule = string.Format("Identity: {0}, Rights: {1}", strUserLoginName, objAccessRule.FileSystemRights);
                        // + " | Type: " + rule.AccessControlType
                        // + " | Propagation Flags: " + rule.PropagationFlags
                        // + " | Inherited : " + rule.IsInherited;

                        //Identity: AVANT\IT | Rights: Read, Synchronize
                        //Identity: AVANT\IT | Rights: ReadAndExecute, Synchronize
                        //Identity: AVANT\seanadm | Rights: FullControl
                        //Identity: AVANT\scottadm | Rights: FullControl
                        //Identity: AVANT\jorgeadm | Rights: FullControl
                        //Identity: AVANT\ensyst | Rights: FullControl
                        //Identity: AVANT\Pivotal to Asclepios migration project DL | Rights: ReadAndExecute, Synchronize
                        //Identity: AVANT\Pivotal to Asclepios migration project | Rights: ReadAndExecute, Synchronize
                        writeDebugInfo(strRule);

                        SPRoleDefinition RoleDefinition = null;
                        string strFileSystemRights = string.Empty;
                        strFileSystemRights = objAccessRule.FileSystemRights.ToString();
                        RoleDefinition = getSPRoleDefinition(objSPWeb, strFileSystemRights);
                        if (RoleDefinition == null)
                        {
                            writeSkippedFileLog(string.Format(@"invalid strFileSystemRights: {0}, strRule: {1}, objSPList.RootFolder.Url: {2}", strFileSystemRights, strRule, objSPList.RootFolder.Url));
                            continue;
                        }

                        SPRoleAssignment RoleAssignment = new SPRoleAssignment(GetSPPrincipal(objSPWeb, strUserLoginName));
                        RoleAssignment.RoleDefinitionBindings.Add(RoleDefinition);
                        objSPList.RoleAssignments.Add(RoleAssignment);
                    }
                }
                objSPList.Update();
            }
            catch (Exception ex)
            {
                writeDebugInfo(string.Format(@"ex.Message={0}, objSPList.RootFolder.Url={1}", ex.Message, objSPList.RootFolder.Url));
                writeDebugInfo(string.Format(@"ex.StackTrace={0}", ex.StackTrace));
            }
            finally
            {
                objSPWeb.AllowUnsafeUpdates = false;
            }

            return true;
        }

        public static bool changeSPListItemRights(SPListItem objSPListItem, AuthorizationRuleCollection objRules)
        {
            if (Settings.Default.CopyPermissions == false)
                return false;

            if (objSPListItem.HasUniqueRoleAssignments == true)
                return false;

            bool boolBreakRoleInheritance = false;
            bool boolPermissionAdded = false;
            SPWeb objSPWeb = objSPListItem.Web;
            string strDomainPrefix = System.Environment.UserDomainName + @"\";

            try
            {
                objSPWeb.AllowUnsafeUpdates = true;

                foreach (System.Security.AccessControl.FileSystemAccessRule objAccessRule in objRules)
                {
                    if (objAccessRule.IsInherited == false && objAccessRule.AccessControlType == AccessControlType.Allow && objAccessRule.IdentityReference.Value.StartsWith(strDomainPrefix, StringComparison.InvariantCultureIgnoreCase))
                    {
                        objSPListItem.BreakRoleInheritance(false);
                        SPRoleDefinition RoleDefinition = objSPWeb.RoleDefinitions.GetByType(SPRoleType.Administrator);
                        SPRoleAssignment RoleAssignment = null;

                        boolPermissionAdded = false;
                        if (Settings.Default.SitesAdminFullControl == true)
                        {
                            RoleAssignment = new SPRoleAssignment((SPPrincipal)objSPWeb.Site.Owner);
                            RoleAssignment.RoleDefinitionBindings.Add(RoleDefinition);
                            objSPListItem.RoleAssignments.Add(RoleAssignment);
                            boolPermissionAdded = true;
                        }

                        if (Settings.Default.SiteOwnersFullControl == true)
                        {
                            RoleAssignment = new SPRoleAssignment((SPPrincipal)objSPWeb.Groups[_WebGroupName_Owners]);
                            RoleAssignment.RoleDefinitionBindings.Add(RoleDefinition);
                            objSPListItem.RoleAssignments.Add(RoleAssignment);
                            boolPermissionAdded = true;
                        }

                        if (boolPermissionAdded == true)
                        {
                            objSPListItem.Update();
                        }
                        boolBreakRoleInheritance = true;
                        break;
                    }
                }
                if (boolBreakRoleInheritance == false)
                {
                    return false;
                }

                foreach (System.Security.AccessControl.FileSystemAccessRule objAccessRule in objRules)
                {
                    if (objAccessRule.AccessControlType == AccessControlType.Allow && objAccessRule.IdentityReference.Value.StartsWith(strDomainPrefix, StringComparison.InvariantCultureIgnoreCase))
                    {
                        string strUserLoginName = objAccessRule.IdentityReference.Value;
                        string strUserDisplayName = strUserLoginName;

                        string strRule = string.Format("Identity: {0}, Rights: {1}", strUserLoginName, objAccessRule.FileSystemRights);
                        // + " | Type: " + rule.AccessControlType
                        // + " | Propagation Flags: " + rule.PropagationFlags
                        // + " | Inherited : " + rule.IsInherited;

                        //Identity: AVANT\IT | Rights: Read, Synchronize
                        //Identity: AVANT\IT | Rights: ReadAndExecute, Synchronize
                        //Identity: AVANT\seanadm | Rights: FullControl
                        //Identity: AVANT\scottadm | Rights: FullControl
                        //Identity: AVANT\jorgeadm | Rights: FullControl
                        //Identity: AVANT\ensyst | Rights: FullControl
                        //Identity: AVANT\Pivotal to Asclepios migration project DL | Rights: ReadAndExecute, Synchronize
                        //Identity: AVANT\Pivotal to Asclepios migration project | Rights: ReadAndExecute, Synchronize
                        writeDebugInfo(strRule);

                        SPRoleDefinition RoleDefinition = null;
                        string strFileSystemRights = string.Empty;
                        strFileSystemRights = objAccessRule.FileSystemRights.ToString();
                        RoleDefinition = getSPRoleDefinition(objSPWeb, strFileSystemRights);
                        if (RoleDefinition == null)
                        {
                            writeSkippedFileLog(string.Format(@"invalid strFileSystemRights: {0}, strRule: {1}, objSPListItem.Url: {2}", strFileSystemRights, strRule, objSPListItem.Url));
                            continue;
                        }
                        SPRoleAssignment RoleAssignment = new SPRoleAssignment(GetSPPrincipal(objSPWeb, strUserLoginName));
                        RoleAssignment.RoleDefinitionBindings.Add(RoleDefinition);
                        objSPListItem.RoleAssignments.Add(RoleAssignment);
                    }
                }
                objSPListItem.UpdateOverwriteVersion();
                if (objSPListItem.ContentType.Name.Equals("Folder", StringComparison.InvariantCultureIgnoreCase))
                {
                    _iFolderPermissionCopied++;
                }
                else
                {
                    _iFilePermissionCopied++;
                }
            }
            catch (Exception ex)
            {
                writeDebugInfo(string.Format(@"ex.Message={0}, objSPListItem.Url={1}", ex.Message, objSPListItem.Url));
                writeDebugInfo(string.Format(@"ex.StackTrace={0}", ex.StackTrace));
            }
            finally
            {
                objSPWeb.AllowUnsafeUpdates = false;
            }

            return true;
        }

        public static SPPrincipal GetSPPrincipal(SPWeb objSPWeb, string strLoginName)
        {
            if (string.IsNullOrEmpty(strLoginName))
                return null;

            SPPrincipal objSPPrincipal = null;
            try
            {
                //SPUtility.ResolvePrincipalInternal(SPWeb web, SPWebApplication webApp, Nullable`1 urlZone, String input, SPPrincipalType scopes, SPPrincipalSource sources, SPUserCollection usersContainer, Boolean inputIsEmailOnly, Boolean alwaysAddWindowsResolver)
                //SPPrincipalInfo info = SPUtility.ResolvePrincipalInternal(objSPWeb, null, null, strLoginName, SPPrincipalType.SecurityGroup | SPPrincipalType.User, SPPrincipalSource.All, null, false, true);
                SPPrincipalInfo info = SPUtility.ResolvePrincipal(objSPWeb, strLoginName, SPPrincipalType.SecurityGroup | SPPrincipalType.User, SPPrincipalSource.All, null, false);
                if (info == null)
                {
                    writeDebugInfo(string.Format(@"GetSPPrincipal() exception, UserCouldNotBeFound, strLoginName={0}", strLoginName));
                    return null;
                    //throw new SPException(SPResource.GetString("UserCouldNotBeFound", new object[] { strLoginName }));
                }
                if (info.PrincipalId < 0)
                {
                    objSPWeb.SiteUsers.Add(info.LoginName, info.Email, info.DisplayName, string.Empty);
                }

                objSPPrincipal = (SPPrincipal)objSPWeb.SiteUsers[strLoginName];
            }
            catch (Exception ex)
            {
                writeDebugInfo(string.Format(@"ex.Message={0}, LoginName={1}", ex.Message, strLoginName));
                writeDebugInfo(string.Format(@"ex.StackTrace={0}", ex.StackTrace));
                return null;
            }

            return objSPPrincipal;
        }

        public static bool IsFileLocked(FileInfo file)
        {
            FileStream stream = null;

            try
            {
                stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            }
            catch (Exception)
            {
                //the file is unavailable because it is:
                //still being written to
                //or being processed by another thread
                //or does not exist (has already been processed)
                return true;
            }
            finally
            {
                if (stream != null)
                    stream.Close();
            }

            //file is not locked
            return false;
        }

        public static int UploadFiles(string strFileFolderPath, SPFolder myParentFolder)
        {
            //writeDebugInfo(string.Format("UploadFiles() begin, strFileFolderPath={0}, myParentFolder.Url={1}, myParentFolder.Files.Count={2}", strFileFolderPath, myParentFolder.Url, myParentFolder.Files.Count));

            int iCount = 0;
            string strTmp = string.Empty;
            DirectoryInfo dirinfo = new DirectoryInfo(strFileFolderPath);

            FileInfo[] oFiles;
            try
            {
                oFiles = dirinfo.GetFiles();
            }
            catch (Exception ex)
            {
                strTmp = string.Format(@"Cannot get files from folder path '{0}'", strFileFolderPath);
                writeSkippedFileLog(strTmp);
                writeDebugInfo(strTmp);
                writeDebugInfo(string.Format(@"UploadFiles(), ex.Message={0}", ex.Message));
                writeDebugInfo(string.Format(@"UploadFiles(), ex.StackTrace={0}", ex.StackTrace));
                return 0;
            }
            iCount = oFiles.Length;
            //writeDebugInfo(string.Format(@"UploadFiles(), oFiles.Length={0}", iCount));
            if (iCount < 1)
                return iCount;

            string strFileName = string.Empty;
            string strFileId = string.Empty;
            long iFileLength = 0;
            string strFileFullName = string.Empty;
            string strFileExtension = string.Empty;
            myParentFolder.ParentWeb.AllowUnsafeUpdates = true;

            SPFileCollection objSPFileCollection = myParentFolder.Files;
            objSPFileCollection.Web.AllowUnsafeUpdates = true;

            bool boolSkipFlag = false;
            SPFile oSPFile = null;
            foreach (FileInfo oCurrentFile in oFiles)
            {
                strFileFullName = string.Empty;
                strFileExtension = string.Empty;
                iFileLength = 0;
                boolSkipFlag = false;
                oSPFile = null;

                try
                {
                    strFileFullName = oCurrentFile.FullName;
                    //writeDebugInfo(string.Format(@"UploadFiles(), strFileFullName={0}", strFileFullName));
                    //Console.ReadLine();

                    try
                    {
                        iFileLength = oCurrentFile.Length;
                        strFileExtension = oCurrentFile.Extension;
                    }
                    catch (Exception)
                    {
                        writeDebugInfo(string.Format(@"Cannot get file length, continue. FullName={0}", strFileFullName));
                    }

                    if (_boolFileNameUniqueID)
                    {
                        strFileName = oCurrentFile.Name;
                    }
                    else
                    {
                        strFileName = convertFileName(oCurrentFile.Name);
                    }
                    if (InvalidFileExtention(oCurrentFile.Extension))
                    {
                        boolSkipFlag = true;
                        writeSkippedFileLog(string.Format(@"invalid file extension({1}), FullName={0}", strFileFullName, strFileExtension));
                    }
                    else if (InvalidFileName(oCurrentFile.Name))
                    {
                        boolSkipFlag = true;
                        writeSkippedFileLog(string.Format(@"invalid file name, FullName={0}", strFileFullName));
                    }
                    else if (CheckFileExists(objSPFileCollection, strFileName, out oSPFile))
                    {
                        boolSkipFlag = true;
                        writeSkippedFileLog(string.Format(@"exists, File.FullName={0}, SiteFolder.Url={1}", oCurrentFile.FullName, myParentFolder.Url));
                    }
                    else if (iFileLength >= _iFileSizeLimit)
                    {
                        boolSkipFlag = true;
                        writeSkippedFileLog(string.Format(@"invalid file length({1}), FullName={0}", strFileFullName, iFileLength));
                    }
                    else if (_strFileTarget.Equals("active", StringComparison.InvariantCultureIgnoreCase) && oCurrentFile.LastWriteTime < _dtInactiveDate && _iFileInactiveMonths > 0)
                    {
                        _iFileActiveSkipped++;
                        boolSkipFlag = true;
                        //writeDebugInfo(string.Format(@"invalid file status (inactive), File.FullName={0}, File.Length={1}", strFileFullName, oCurrentFile.Length));
                    }
                    else if (_strFileTarget.Equals("inactive", StringComparison.InvariantCultureIgnoreCase) && oCurrentFile.LastWriteTime >= _dtInactiveDate && _iFileInactiveMonths > 0)
                    {
                        _iFileInactiveSkipped++;
                        boolSkipFlag = true;
                        //writeDebugInfo(string.Format(@"invalid file status (active), File.FullName={0}, File.Length={1}", strFileFullName, oCurrentFile.Length));
                    }

                    //writeDebugInfo(string.Format(@"boolSkipFlag={0}, _boolCopyFiles={1}", boolSkipFlag, _boolCopyFiles));

                    if (boolSkipFlag == false && _boolCopyFiles == true)
                    {
                        oSPFile = uploadFile(oCurrentFile, myParentFolder, strFileId);

                        _iFileCopied++;
                    }

                    if (oSPFile == null)
                    {
                        //writeDebugInfo(string.Format(@"File doesn't exist on SharePoint, but is ignored by settings. strFileName={0}, oCurrentFile.Name={1}", strFileName, oCurrentFile.Name));
                        //writeDebugInfo(string.Format(@"boolSkipFlag={0}, boolCopyFiles={1}", boolSkipFlag, boolCopyFiles));
                        continue;
                    }

                    //if (_boolCopyPermissions == true && oSPFile != null)
                    //{
                    //    FileSecurity objFileSecurity = oCurrentFile.GetAccessControl();
                    //    AuthorizationRuleCollection objRules = objFileSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
                    //    changeSPListItemRights(oSPFile.Item, objRules);
                    //}
                }
                catch (Exception ex)
                {
                    if (ex.Message.Contains(@" blocked "))
                    {
                        writeSkippedFileLog(string.Format(@"Blocked, File.FullName={0}", strFileFullName));
                        continue;
                    }
                    else if (ex.Message.Contains(@"cannot be accessed"))
                    {
                        _boolFileLockFlag = true;
                        writeSkippedFileLog(string.Format(@"Cannot access, File.FullName={0}", strFileFullName));
                        continue;
                    }
                    else if (ex.Message.Contains(@"being used by another process"))
                    {
                        writeSkippedFileLog(string.Format(@"Locked(being used by another process), File.FullName={0}", strFileFullName));
                        continue;
                    }
                    else
                    {
                        writeSkippedFileLog(string.Format(@"unknown issue, File.FullName={1}\{0}", oCurrentFile.Name, strFileFolderPath));
                        writeDebugInfo(string.Format(@"ex.Message={0}, File.FullName={1}\{2}", ex.Message, strFileFolderPath, oCurrentFile.Name));
                        writeDebugInfo(string.Format(@"ex.StackTrace={0}", ex.StackTrace));
                    }
                    try
                    {
                        writeDebugInfo(string.Format(@"Exception: Length={0}, File.FullName={1}\{2}", iFileLength, strFileFolderPath, oCurrentFile.Name));
                    }
                    catch
                    {
                        ;
                    }
                }
            }   //end of "foreach()"

            if (objSPFileCollection != null)
            {
                objSPFileCollection.Web.AllowUnsafeUpdates = false;
            }
            if (myParentFolder != null)
                myParentFolder.ParentWeb.AllowUnsafeUpdates = false;

            writeDebugInfo(string.Format(@"Folder '{0}' files uploaded. Files count={1}", strFileFolderPath, iCount));

            return 0;
        }

        public static bool CheckFileExists(SPFileCollection destFiles, string strFileName, out SPFile objSPFile)
        {
            string strFile = string.Empty;
            bool fileExists = false;
            objSPFile = null;
            for (int noOfFile = 0; noOfFile < destFiles.Count; noOfFile++)
            {
                SPFile tempFile = destFiles[noOfFile];

                if (_boolFileNameUniqueID)
                {
                    strFile = tempFile.Title;
                }
                else
                {
                    strFile = tempFile.Name;
                }

                //if (tempFile.Name.Equals(strFileName, StringComparison.InvariantCultureIgnoreCase))
                if (strFile.Equals(strFileName, StringComparison.InvariantCultureIgnoreCase))
                {
                    //writeDebugInfo(string.Format(@"File '{0}' exists at '{1}'.  Skipped.", strFileName, tempFile.ServerRelativeUrl));
                    //writeDebugInfo(string.Format(@"destFiles.Folder.Count='{0}', destFiles.Folder.ServerRelativeUrl='{1}'.", destFiles.Count, destFiles.Folder.ServerRelativeUrl));
                    fileExists = true;
                    objSPFile = tempFile;
                    break;
                }
            }
            return fileExists; //return bool values depends upon the file check.   
        }

        public static bool InvalidFileExtention(string strFileExtension)
        {
            bool fileInvalid = false;

            if (string.IsNullOrEmpty(strFileExtension))
            {
                fileInvalid = true;
                return fileInvalid;
            }

            if (strFileExtension.StartsWith(@"."))
                strFileExtension = strFileExtension.Substring(1);

            foreach (string item in _strInvalidFileExtensionsArray)
            {
                if (string.IsNullOrEmpty(item)) continue;

                if (item.Equals(strFileExtension, StringComparison.InvariantCultureIgnoreCase))
                {
                    fileInvalid = true;
                    break;
                }
            }

            foreach (string item in _blockedFileTypes)
            {
                if (item.Equals(strFileExtension, StringComparison.InvariantCultureIgnoreCase))
                {
                    fileInvalid = true;
                    break;
                }
            }

            return fileInvalid;
        }

        public static bool InvalidFileName(string strFileName)
        {
            bool fileInvalid = false;

            if (strFileName.StartsWith(@"~"))
                fileInvalid = true;

            if (strFileName.Equals(@"thumbs.db", StringComparison.InvariantCultureIgnoreCase))
                fileInvalid = true;

            return fileInvalid;
        }

        public static string convertListName(string strName)
        {
            if (string.IsNullOrEmpty(strName))
                return string.Empty;

            string strReturn = convertFolderName(strName);
            string[] strInvalidCharArray = new string[] { @".", @"(", @")", @"'", @"," };

            foreach (string strInvalid in strInvalidCharArray)
            {
                strReturn = strReturn.Replace(strInvalid, "");
            }

            strReturn = strReturn.Trim();
            if (strReturn.Length > 50)
            {
                strReturn = strReturn.Substring(0, 50);
            }

            return strReturn;
        }

        public static string convertFolderName(string strName)
        {
            if (string.IsNullOrEmpty(strName))
                return string.Empty;

            string strReturn = convertFileName(strName);
            char[] charInvalidCharArray = new char[] { '-' };

            foreach (char charInvalid in charInvalidCharArray)
            {
                strReturn = strReturn.Replace(charInvalid, '_');
            }
            //strReturn = strReturn.Replace(@".", "");

            if (strReturn.Equals("Forms", StringComparison.InvariantCultureIgnoreCase))
            {
                strReturn += @"_";
            }
            if (strReturn.Equals("_vti_cnf", StringComparison.InvariantCultureIgnoreCase))
            {
                strReturn = @"vti cnf";
            }
            while (strReturn.StartsWith(@"_"))
            {
                strReturn = strReturn.Substring(1) + @"_";
            }

            strReturn = strReturn.Trim();

            return strReturn;
        }

        public static string convertFileName(string strName)
        {
            if (string.IsNullOrEmpty(strName))
                return string.Empty;

            string strSuffixCorrected = string.Empty;
            string strReturn = strName;
            char[] charInvalidCharArray = new char[] { '"', '#', '%', '&', '*', ':', '<', '>', '?', '\\', '/', '{', '|', '}', '~' };
            // http://www.sysadminsblog.com/tag/sharepoint-2010/
            string[] strInvalidSuffix = new string[] { @".files", @"_files", @"-Dateien", @"_fichiers", @"_bestanden", @"_file",
                @"_archivos", @"-filer", @"_tiedostot", @"_pliki", @"_soubory", @"_elemei", @"_ficheiros", @"_arquivos", @"_dosyalar",
                @"_datoteke", @"_fitxers", @"_failid", @"_fails", @"_bylos", @"_fajlovi", @"_fitxategiak"};

            foreach (char charInvalid in charInvalidCharArray)
            {
                if (strReturn.IndexOf(charInvalid) >= 0)
                {
                    strReturn = strReturn.Replace(charInvalid, '_');
                }
            }
            foreach (string strSuffix in strInvalidSuffix)
            {
                if (strReturn.EndsWith(strSuffix, StringComparison.InvariantCultureIgnoreCase))
                {
                    strSuffixCorrected = @" " + strSuffix.Substring(1);
                    strReturn = strReturn.Replace(strSuffix, strSuffixCorrected);
                }
            }
            while (strReturn.IndexOf(@"..") > 0)
            {
                strReturn = strReturn.Replace(@"..", @".");
            }
            while (strReturn.StartsWith(@"."))
            {
                strReturn = strReturn.Substring(1);
            }

            if (strReturn.Length > 128)
            {
                string strExtension = string.Empty;
                int iPos = int.MinValue;
                iPos = strReturn.LastIndexOf('.');
                if (iPos > 0)
                {
                    strExtension = strReturn.Substring(iPos);
                }
                else
                {
                    iPos = strReturn.Length;
                }
                if (iPos > 123)
                    iPos = 123;
                strReturn = strReturn.Substring(0, iPos) + strExtension;
            }

            return strReturn.Trim();
        }

        public static string toBase62String(long value)
        {
            //  http://d.hatena.ne.jp/tilfin/20100622/1277176778

            long val = value;

            StringBuilder sb = new StringBuilder(7);
            while (val > 0)
            {
                int mod = (int)(val % 62);
                if (mod < 10)
                {
                    sb.Append(mod);
                }
                else if (mod < 36)
                {
                    mod += 87;
                    sb.Append((char)mod);
                }
                else
                {
                    mod += 29;
                    sb.Append((char)mod);
                }
                val = val / 62;
            }

            return sb.ToString();
        }

        public static string GenerateId(string strFileExtension)
        {   //http://madskristensen.net/post/Generate-unique-strings-and-numbers-in-C.aspx
            string strId = string.Empty;

            byte[] buffer = Guid.NewGuid().ToByteArray();
            long lUniqueId = BitConverter.ToInt64(buffer, 0);
            //strId = lUniqueId.ToString("X") + strFileExtension;

            //strId = Convert.ToBase64String(buffer, 0, 8).Substring(5, 6) + strFileExtension;

            strId = toBase62String(lUniqueId) + strFileExtension;

            //long i = 1;
            //foreach (byte b in Guid.NewGuid().ToByteArray())
            //{
            //    i *= ((int)b + 1);
            //}
            //strId = string.Format("{0:x}", i - DateTime.Now.Ticks) + strFileExtension;

            return strId;
        }
    }
}
